package com.unknow.first.api.encrypt.util;

import static org.cloud.constant.ApiEncryptConstant.__USER_API_HASH_MAP_KEY;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.unknow.first.api.encrypt.ApiEncryptType;
import com.unknow.first.api.encrypt.config.ApiEncryptConfig;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.cloud.context.RequestContextManager;
import org.cloud.core.redis.RedisUtil;
import org.cloud.exception.BusinessException;
import org.cloud.utils.AES128Util;
import org.cloud.vo.CommonApiResult;

public final class ApiEncryptUtil {

    private ApiEncryptUtil() {

    }

    /**
     * 加解密方法，可以直接在代码中对数据进行加密操作
     *
     * @param result
     * @param apiEncryptType
     * @throws Exception
     */
    public static void encryptData(CommonApiResult<Object> result, ApiEncryptType apiEncryptType) throws Exception {
        if (ApiEncryptType.BY_SYSTEM.equals(apiEncryptType)) {
            String aesStr = AES128Util.single()
                .encrypt(JSON.toJSONString(result.getData()), ApiEncryptConfig.getApiAesKey(), ApiEncryptConfig.getApiAesIv());
            result.setData(aesStr);
        } else if (ApiEncryptType.BY_USER.equals(apiEncryptType)) {
            Long userId = RequestContextManager.single().getRequestContext().getUser().getId();
            List<String> aesKeyAndIv = getApiEncryptKey(userId);
            String aesStr = AES128Util.single().encrypt(JSON.toJSONString(result.getData()), aesKeyAndIv.get(0), aesKeyAndIv.get(1));
            result.setData(aesStr);
        } else {
            throw new BusinessException("不支持的api加密方式");
        }
        result.setEncryptType(apiEncryptType.name());
    }

    public static List<String> saveOrUpdateApiEncryptKey(Long userId) {
        final String aesKey = RandomUtil.randomString(16);
        final String aesIV = RandomUtil.randomString(16);
        List<String> apiEncryptKey = Arrays.asList(aesKey, aesIV);
        // 将当前用户api的key写入到redis中，每次登录都会更换，所以需要加解密的api只能登录一个客户端
        List<String> encryptKey = apiEncryptKey.stream().map(ApiEncryptUtil::getAesEncValue).collect(Collectors.toList());
        RedisUtil.single().hashSet(__USER_API_HASH_MAP_KEY, String.valueOf(userId), encryptKey);
        return apiEncryptKey;
    }

    public static List<String> getApiEncryptKey(Long userId) {
        List<String> encryptKey = RedisUtil.single().hashGet(__USER_API_HASH_MAP_KEY, String.valueOf(userId));
        return encryptKey.stream().map(ApiEncryptUtil::getAesDecValue).collect(Collectors.toList());
    }

    private static String getAesEncValue(String item) {
        try {
            return AES128Util.single().encrypt(item);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String getAesDecValue(String item) {
        try {
            return AES128Util.single().decrypt(item);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
